/*
 * Copyright (c) 2021 hpmicro
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 */

#include "board.h"
#include <math.h>
#include <stdio.h>
#include "hpm_debug_console.h"
#include "hpm_sysctl_drv.h"
#include "hpm_clock_drv.h"
#include "hpm_i2s_drv.h"
#include "hpm_dao_drv.h"
#include "hpm_soc.h"

#define TEST_DAO HPM_DAO
#define I2S_MCLK_FREQ_IN_HZ (24576000UL)
#define DAO_I2S_CLK_NAME clock_dao

#define VOLUME_SCALE_SHIFT (2U)

// 默认32位采样深度
#define MAX_SAMPLE_VALUE (UINT32_MAX / 64)

static uint32_t t_freq;
static uint32_t t_start;

static void seconds_init()
{
    t_freq = clock_get_frequency(clock_mchtmr0);
    t_start = HPM_MCHTMR->MTIME;
}

static float seconds_get()
{
    uint32_t current = HPM_MCHTMR->MTIME;
    return (current - t_start) / (float) t_freq;
}

void sine_wave_to_dao(uint32_t freq, uint32_t ms)
{
    uint32_t i, j, data;
    i2s_config_t i2s_config = {0};
    i2s_transfer_config_t transfer = {0};
    dao_config_t dao_config = {0};

    i2s_get_default_config(DAO_I2S, &i2s_config);
    i2s_init(DAO_I2S, &i2s_config);
    /*
     * config transfer for DAO
     */
    i2s_get_default_transfer_config_for_dao(&transfer);
    if (status_success != i2s_config_tx(DAO_I2S, I2S_MCLK_FREQ_IN_HZ, &transfer))
    {
        printf("I2S config failed for DAO\n");
        while(1);
    }
    printf("sample_rate: %d\n", transfer.sample_rate);

    dao_get_default_config(TEST_DAO, &dao_config);
    if (status_success != dao_init(TEST_DAO, &dao_config)) {
        printf("failed to initialize DAO\n");
        while(1);
    }

    // 现模拟一个freq的正弦波， 例如400Hz
    // T = 1/freq
    // y = A * sin(kt), T = 2*pi / k
    // => k = 2*pi / T = 2*pi*freq
    dao_start(TEST_DAO);
    printf("Playing start ...\n");

    seconds_init();
    float start_time = seconds_get();
    float stop_time = start_time + ms / 1000.0f;
    while (1) {
        float t = seconds_get();
        if (t >= stop_time) break;

        if (i2s_get_tx_line_fifo_level(DAO_I2S, 0) <= 2){
            // y = A * sin(kt)
            data = sinf(2 * M_PI * freq * t) * MAX_SAMPLE_VALUE;
            data <<= VOLUME_SCALE_SHIFT;
            // for (j = 0; j < DAO_SOC_VAD_SAMPLE_RATE_RATIO; j++) 
            {
                i2s_send_data(DAO_I2S, 0, &data, 1); /* Left channel */
                i2s_send_data(DAO_I2S, 0, &data, 1); /* Right channel */
            }
        }
    }
    printf("Playing done! %.3f, %.3f\n", start_time, stop_time);
}

int main(void)
{
    board_init();
    board_init_dao_clock();

    init_dao_pins();

    printf("dao example\n");
    sine_wave_to_dao(400, 1000);

    while(1);
    return 0;
}
